﻿using System.Text.RegularExpressions;

namespace Code2Table.Core;

public static class ClassParser
{
    // 移除了 RegexOptions.Singleline
    // 将 attr 分组中的 (.*?) 替换为 ([\s\S]*?) 以允许特性跨行
    // 移除了 RegexOptions.Singleline
    // 将 attr 分组中的 (.*?) 替换为 ([\s\S]*?) 以允许特性跨行
    private static readonly Regex PropertyRegex = new(
        @"(?<xml>(?:\s*///[^\r\n]*\r?\n)*)                  # XML注释（多行）
            (?<attr>(?:\s*\[\s*\w+(?:\(([\s\S]*?)\))?\s*\]\s*)*)    # 属性特性（多行）
            \s* # (Fix) 允许特性/XML和修饰符间的空白
            (?:public|protected|internal|private)?\s* # 修饰符
            (?!class|interface|record)\b                    # 排除class定义
            (?<type>[A-Za-z0-9_<>\[\]\?.]+)\s+              # 属性类型
            (?<name>\w+)\s* # 属性名
            \{\s*(?<access>[^}]+)\}\s* # 访问器
          ",
        // 关键修复：移除了 RegexOptions.Singleline
        RegexOptions.Compiled | RegexOptions.IgnorePatternWhitespace);

    public static List<PropertyInfoModel> Parse(string classText)
    {
        var list = new List<PropertyInfoModel>();

        foreach (Match match in PropertyRegex.Matches(classText))
        {
            var xml = match.Groups["xml"].Value;
            var attr = match.Groups["attr"].Value;
            var type = match.Groups["type"].Value.Trim();
            var name = match.Groups["name"].Value.Trim();
            var access = match.Groups["access"].Value;

            var descFromXml = ExtractXmlSummary(xml);
            var descFromAttr = ExtractDescription(attr);

            // 检查是否包含 "set;" 关键字
            bool hasSet = access.Contains("set;");
            // 检查 "set;" 是否是公共的
            bool isPublicSet = hasSet &&
                               !Regex.IsMatch(access, @"(private|protected|internal)\s+set;");

            // 使用 Regex 确保匹配到的是 [Required] 特性
            var isRequired = Regex.IsMatch(attr, @"\[\s*Required(Attribute)?\b");

            var model = new PropertyInfoModel
            {
                Name = name,
                Type = type,
                // 优先使用 Display 特性，否则回退到 XML 注释
                Description = !string.IsNullOrWhiteSpace(descFromAttr) ? descFromAttr : descFromXml,

                IsReadOnly = !isPublicSet, // 如果没有公共的 setter，则为只读
                IsRequired = isRequired,
                MaxLength = ExtractInt(attr, "MaxLength") ?? ExtractInt(attr, "StringLength"),
                Range = ExtractRange(attr),
                ColumnType = ExtractColumnType(attr),
            };

            list.Add(model);
        }

        return list;
    }

    // ---------------- 工具方法 (正则已强化) ----------------

    private static int? ExtractInt(string input, string name)
    {
        // 强化：允许特性有多个参数，如 [MaxLength(50, ...)]
        var m = Regex.Match(input, $@"\[\s*{name}\s*\(\s*(\d+)\s*(?:,[\s\S]*)?\)\]");
        return m.Success ? int.Parse(m.Groups[1].Value) : null;
    }

    private static string ExtractRange(string input)
    {
        // 强化：允许特性有多个参数
        var m = Regex.Match(input, @"\[\s*Range\s*\(\s*(\d+)\s*,\s*(\d+)\s*(?:,[\s\S]*)?\s*\)\]");
        return m.Success ? $"{m.Groups[1].Value}-{m.Groups[2].Value}" : string.Empty;
    }

    private static string ExtractDescription(string input)
    {
        // 强化：允许 Display 特性有其他参数，如 [Display(Name = "...", Order = 1)]
        // 使用 [\s\S] 替代 . 来允许跨行
        var m = Regex.Match(input, @"\[\s*Display\s*\([\s\S]*?Name\s*=\s*""(.*?)"".*?\)\]");
        return m.Success ? m.Groups[1].Value : string.Empty;
    }

    private static string ExtractColumnType(string input)
    {
        // 强化：允许 Column 特性有其他参数
        var m = Regex.Match(input, @"\[\s*Column\s*\([\s\S]*?TypeName\s*=\s*""(.*?)""[\s\S]*?\)\]");
        return m.Success ? m.Groups[1].Value : string.Empty;
    }

    /// <summary>
    /// 提取 XML 注释中的 summary / remarks
    /// </summary>
    private static string ExtractXmlSummary(string xml)
    {
        if (string.IsNullOrWhiteSpace(xml))
            return string.Empty;

        // 把每行的 “///” 去掉，留下纯文本
        var cleaned = string.Join("\n",
            xml.Split('\n')
               .Select(line => line.Trim())
               .Where(l => l.StartsWith("///"))
               .Select(l => l.TrimStart('/').Trim())
        );

        // 匹配 summary 段落
        var summaryMatch = Regex.Match(cleaned,
            @"<summary>([\s\S]*?)</summary>", // 使用 ([\s\S]*?) 替代 (.*?)
            RegexOptions.IgnoreCase);

        string summary = summaryMatch.Success
            ? summaryMatch.Groups[1].Value.Replace("\r", "").Replace("\n", " ").Trim()
            : string.Empty;

        summary = Regex.Replace(summary, @"\s+", " ").Trim();

        // 匹配 remarks 段落（可选）
        var remarksMatch = Regex.Match(cleaned,
            @"<remarks>([\s\S]*?)</remarks>", // 使用 ([\s\S]*?) 替代 (.*?)
            RegexOptions.IgnoreCase);

        string remarks = remarksMatch.Success
            ? remarksMatch.Groups[1].Value.Replace("\r", "").Replace("\n", " ").Trim()
            : string.Empty;

        remarks = Regex.Replace(remarks, @"\s+", " ").Trim();

        // 合并两者
        if (!string.IsNullOrWhiteSpace(summary) && !string.IsNullOrWhiteSpace(remarks))
            return $"{summary}（{remarks}）";

        if (string.IsNullOrWhiteSpace(summary))
            return remarks;

        return summary;
    }
}